package local;

import java.util.ArrayList;

public class BiGrafo {
    public ArrayList<Node> v1;
    public ArrayList<Node> v2;
    public ArrayList<Node> iv1;
    public ArrayList<Node> iv2;
    public ArrayList<int[]> iEjes;
    public Integer[] posV1;
    public Integer[] posV2;
    public int cruces;
    public boolean actualizado;

    //Constructor
    public BiGrafo(){
    	v1 = new ArrayList<Node>();
    	v2 = new ArrayList<Node>();
    	
    	iv1 = new ArrayList<Node>();
    	iv2 = new ArrayList<Node>();
    	iEjes = new ArrayList<int[]>();
    	
    }
    
    public BiGrafo(ArrayList<Node> cv1, ArrayList<Node> cv2)
    {
            v1 = cv1;
            posV1 = new Integer[v1.size()];
            v2 = cv2;
            cruces=cantidadCruces();
            actualizado=true;
    }
    
    
    public void contruyeArreglosDePosiciones()
    {
        posV1 = new Integer[v1.size()+iv1.size()];
        // Armo el arreglo con las posiciones de las etiquetas
        int i=0;
        int pos = 0;
        while (i<posV1.length)
        {
            if(v1.size() > i)
            {
                pos = v1.get(i).v;
                posV1[pos]=i;
            }
            i++;
        }
        posV2 = new Integer[v2.size()+iv2.size()];
        // Idem para v2
        i=0;
        while (i<posV2.length)
        {
            if(v2.size() > i)
            {
                pos = v2.get(i).v-v1.size()-iv1.size();
                posV2[pos]=i;
            }
            i++;
        }
    }

    public boolean Adyacente(Node ni, Node nj)
    {
    	for(Node n : ni.ady){
    		if(nj.equals(n)) return true;
    	}
        return false;
    }
    
    public int cantidadCruces()
    {
   //     if (!actualizado)
   //     {
            // Armo el arreglo con las posiciones de las etiquetas
            contruyeArreglosDePosiciones();
            cruces=0; // Me preparo para contar..
            // Recorro todos los vértices y analizo cuales vertices de la otra particion tienen ejes que se cruzan
            int v=0;
            while (v<v1.size())
            {
                ArrayList<Node> adytsv1 = v1.get(v).ady;//g.adyacentes(V1[v].intValue()); //Obtengo los ejes adyacentes al vertice
                int nroEje=0;  // Contador para ir analizando los ejes.
                while (nroEje<adytsv1.size())
                {
                    // Recorro los ejes de todos los vertices siguientes al elegido
                    int vertice2=v+1;
                    while (vertice2<v1.size())
                    {
                        ArrayList<Node> adytsv2 = v1.get(vertice2).ady;//g.adyacentes(V1[vertice2].intValue());
                        int looper=0;
                        Integer verticeAux;
                        while (looper<adytsv2.size())
                        {
                            verticeAux=adytsv2.get(looper).v;
                            if(posV2[verticeAux.intValue()-v1.size()-iv1.size()] != null && posV2[adytsv1.get(nroEje).v-v1.size()-iv1.size()] != null)
                             {
                                if (posV2[verticeAux.intValue()-v1.size()-iv1.size()]<posV2[adytsv1.get(nroEje).v-v1.size()-iv1.size()])
                                {
                                    cruces++;
                                }
                            }
                            looper++;
                        }
                        vertice2++;
                    }
                    nroEje++;
                }
                v++;
            }
   //     }
        actualizado=true;
        return cruces;
    }

    public int CantCortesAfterSwapV1(int PosNodoA, int PosNodoB)
    {
    	int crucesActual = cruces;
        crucesActual = crucesActual - CortesDeV1(PosNodoA);
        crucesActual = crucesActual - CortesDeV1(PosNodoB);
        SwapV1(PosNodoA,PosNodoB);
        crucesActual = crucesActual + CortesDeV1(PosNodoA);
        crucesActual = crucesActual + CortesDeV1(PosNodoB);
        SwapV1(PosNodoA,PosNodoB);
        return crucesActual; 
	}
    	
    public void ConfirmarSwapV1(int PosNodoA, int PosNodoB)
    {
    	SwapV1(PosNodoA,PosNodoB);
    	actualizado=true;
    }    
    public int CortesDeV1(int PosNodo)
    {
        int crucesDe = 0;
        ArrayList<Node> adytsv1 = v1.get(PosNodo).ady;//g.adyacentes(V1[v].intValue()); //Obtengo los ejes adyacentes al vertice
        int nroEje=0;  // Contador para ir analizando los ejes.
        while (nroEje<adytsv1.size())
        {
            // Recorro los ejes de todos los vertices siguientes al elegido
            int vertice2=PosNodo+1;
            while (vertice2<v1.size())
            {
                ArrayList<Node> adytsv2 = v1.get(vertice2).ady;//g.adyacentes(V1[vertice2].intValue());
                int looper=0;
                Integer verticeAux;
                while (looper<adytsv2.size())
                {
                    verticeAux=adytsv2.get(looper).v;
                    if(posV2[verticeAux.intValue()-v1.size()-iv1.size()] != null && posV2[adytsv1.get(nroEje).v-v1.size()-iv1.size()] != null)
                    {
                        if (posV2[verticeAux.intValue()-v1.size()-iv1.size()]<posV2[adytsv1.get(nroEje).v-v1.size()-iv1.size()])
                        {
                            crucesDe++;
                        }
                    }
                    looper++;
                }
                vertice2++;
            }
            nroEje++;
        }
        return crucesDe;
   }
        
    public int CantCortesAfterSwapV2(int PosNodoA, int PosNodoB)
    {
    	int crucesActual = cruces;
        crucesActual = crucesActual - CortesDeV2(PosNodoA);
        crucesActual = crucesActual - CortesDeV2(PosNodoB);
        SwapV1(PosNodoA,PosNodoB);
        crucesActual = crucesActual + CortesDeV2(PosNodoA);
        crucesActual = crucesActual + CortesDeV2(PosNodoB);
        SwapV1(PosNodoA,PosNodoB);
        return crucesActual; 
    }
    	
    public void ConfirmarSwapV2(int PosNodoA, int PosNodoB)
    {
    	SwapV2(PosNodoA,PosNodoB);
    	actualizado=true;
    }
    
    public int CortesDeV2(int PosNodo)
    {
        int crucesDe = 0;
        ArrayList<Node> adytsv2 = v2.get(PosNodo).ady;//g.adyacentes(V1[v].intValue()); //Obtengo los ejes adyacentes al vertice
        int nroEje=0;  // Contador para ir analizando los ejes.
        while (nroEje<adytsv2.size())
        {
            // Recorro los ejes de todos los vertices siguientes al elegido
            int vertice2=PosNodo+1;
            while (vertice2<v2.size())
            {
                ArrayList<Node> adytsv1 = v2.get(vertice2).ady;//g.adyacentes(V1[vertice2].intValue());
                int looper=0;
                Integer verticeAux;
                while (looper<adytsv1.size())
                {
                    verticeAux=adytsv1.get(looper).v;
                    if(posV1[verticeAux.intValue()] != null && posV1[adytsv2.get(nroEje).v] != null)
                    {
                        if (posV1[verticeAux.intValue()]<posV1[adytsv2.get(nroEje).v])
                        {
                            crucesDe++;
                        }
                    }
                    looper++;
                }
                vertice2++;
            }
            nroEje++;
        }
        return crucesDe;
    }
	
	
    public void SwapV1(int a, int b)
    {
    	Integer aAfterSwap = v1.get(a).v;
    	v1.get(a).v = v1.get(b).v;
    	v1.get(b).v = aAfterSwap;
    }

    public void SwapV2(int a, int b)
    {
    	Integer aAfterSwap = v2.get(a).v;
    	v2.get(a).v = v2.get(b).v;
    	v2.get(b).v = aAfterSwap;
    }    
    
    
    
    
      public void mainBi() {
    	  	//BiGrafo big = new BiGrafo();
    	  	/* Grafo ejemplo:
    	  	 *   
    	  	 *   v1  v2
    	  	 *   
    	  	 * 	 0   1
    	  	 *        \ /
    	  	 *         X	
    	  	 *	  / \  
    	  	 *       2   3
      		 */
    	  	
    	  	Node n1 = new Node(0,false);
    	  	Node n2 = new Node(1,false);
    	  	Node n3 = new Node(2,false);
    	  	Node n4 = new Node(3,false);
    	  	 
    	  	 // agrego las adyacencias
    	  	 n1.ady.add(n4);
    	  	 n2.ady.add(n3);
    	   	 n3.ady.add(n2);
    	   	 n4.ady.add(n1);
    	  	 
    	  	 // agrego los nodos a los conjuntos
    	  	 v1.add(n2);
    	  	 v1.add(n1);
    	  	 v2.add(n4);
    	  	 v2.add(n3);
                contruyeArreglosDePosiciones();                 
                cruces=cantidadCruces();
                actualizado=true;                 
      }
  
}

